package com.office.automate.service.impl.report;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.office.automate.dataaccess.def.leave.EmployeeLeaveDao;
import com.office.automate.dataaccess.def.payrole.MonthlyEmployeePayroleDao;
import com.office.automate.dataaccess.impl.administration.PublicHolidayDaoImplementer;
import com.office.automate.dataaccess.impl.leave.EmployeeLeaveDaoImplementer;
import com.office.automate.dataaccess.impl.payrole.MonthlyEmployeePayroleDaoImplementer;
import com.office.automate.dataaccess.impl.user.EmployeeDaoImplementer;
import com.office.automate.exception.framework.FrontierVisibleException;
import com.office.automate.frontier.utility.DataConversionUtility;
import com.office.automate.model.leave.LeaveRequest;
import com.office.automate.model.leave.LeaveSummaryDetails;
import com.office.automate.model.payrole.MonthlyEmployeePayrole;
import com.office.automate.model.report.EmployeeLeaveDetailsRequest;
import com.office.automate.model.report.EmployeeSalaryDetails;
import com.office.automate.model.report.EmployeeSalaryDetailsRequest;
import com.office.automate.model.report.MonthlyCoinAnalysis;
import com.office.automate.service.def.report.ReportingService;

public class ReportingServiceImplementer implements ReportingService {

	private EmployeeLeaveDao employeeLeaveDao = new EmployeeLeaveDaoImplementer();
	private MonthlyEmployeePayroleDao monthlyEmployeePayroleDao = new MonthlyEmployeePayroleDaoImplementer();
	private DataConversionUtility dtUtility = new DataConversionUtility();

	public List<LeaveRequest> getEmployeeLeaveDetails(EmployeeLeaveDetailsRequest anEmployeeLeaveDetailsRequest) throws FrontierVisibleException {
		
		return employeeLeaveDao.getEmployeeLeaveDetails(anEmployeeLeaveDetailsRequest);
		
	}

	public MonthlyCoinAnalysis getMonthlyCoinAnalysisDetails(String billingPeriod) throws FrontierVisibleException {
		MonthlyCoinAnalysis monthlyCoinAnalysisList = null;
		List<MonthlyEmployeePayrole> monthlyPayroleList = monthlyEmployeePayroleDao.getEmployeeSalaryDetailsByBillingPeriod(billingPeriod);
		
		if (monthlyPayroleList != null) {
			monthlyCoinAnalysisList = new MonthlyCoinAnalysis();
			for (MonthlyEmployeePayrole employeePay : monthlyPayroleList) {
				if ("Cheque".equals(employeePay.getPaymentMethod())) {
					continue;
				}
				double capital = employeePay.getBankPayment();
				monthlyCoinAnalysisList.setAmountToBePayByCash(monthlyCoinAnalysisList.getAmountToBePayByCash() + capital);
				int billsCount = 0;
				// 5000 Bills Count
				billsCount = (int) (capital / 5000);
				monthlyCoinAnalysisList.setFiveThousandRupeeBillsCount(monthlyCoinAnalysisList.getFiveThousandRupeeBillsCount() + billsCount);
				capital = capital - (5000 * billsCount);

				// 2000 Bills Count
				billsCount = (int) (capital / 2000);
				monthlyCoinAnalysisList.setTwothousandReupeeBillsCount(monthlyCoinAnalysisList.getTwothousandReupeeBillsCount() + billsCount);
				capital = capital - (2000 * billsCount);
				
				// 1000 Bills Count
				billsCount = (int) (capital / 1000);
				monthlyCoinAnalysisList.setThousandRupeeBillsCount(monthlyCoinAnalysisList.getThousandRupeeBillsCount() + billsCount);
				capital = capital - (1000 * billsCount);

				// 500 Bills Count
				billsCount = (int) (capital / 500);
				monthlyCoinAnalysisList.setFiveHundredRupeeBillsCount(monthlyCoinAnalysisList.getFiveHundredRupeeBillsCount() + billsCount);
				capital = capital - (500 * billsCount);
				
				// 100 Bills Count
				billsCount = (int) (capital / 100);
				monthlyCoinAnalysisList.setHundredRupeeBillsCount(monthlyCoinAnalysisList.getHundredRupeeBillsCount() + billsCount);
				capital = capital - (100 * billsCount);

				// 50 Bills Count
				billsCount = (int) (capital / 50);
				monthlyCoinAnalysisList.setFiftyRupeeBillsCount(monthlyCoinAnalysisList.getFiftyRupeeBillsCount() + billsCount);
				capital = capital - (50 * billsCount);

				// 20 Bills Count
				billsCount = (int) (capital / 20);
				monthlyCoinAnalysisList.setTwentyRupeeBillsCount(monthlyCoinAnalysisList.getTwentyRupeeBillsCount() + billsCount);
				capital = capital - (20 * billsCount);
				
				// 10 Bills Count
				billsCount = (int) (capital / 10);
				monthlyCoinAnalysisList.setTenRupeeBillsCount(monthlyCoinAnalysisList.getTenRupeeBillsCount() + billsCount);
				capital = capital - (10 * billsCount);
				
				// 5 Coins Count
				billsCount = (int) (capital / 5);
				monthlyCoinAnalysisList.setFiveRupeeCoinCount(monthlyCoinAnalysisList.getFiveRupeeCoinCount() + billsCount);
				capital = capital - (5 * billsCount);				

				// 2 Coins Count
				billsCount = (int) (capital / 2);
				monthlyCoinAnalysisList.setTwoRupeeCoinCount(monthlyCoinAnalysisList.getTwoRupeeCoinCount() + billsCount);
				capital = capital - (2 * billsCount);
				
				// 1 Coins Count
				billsCount = (int) (capital / 1);
				monthlyCoinAnalysisList.setOneRupeeCoinCount(monthlyCoinAnalysisList.getOneRupeeCoinCount() + billsCount);
				capital = capital - (1 * billsCount);

				// .50 Coins Count
				billsCount = (int) (capital / 0.50);
				monthlyCoinAnalysisList.setFiftyCentCoinCount(monthlyCoinAnalysisList.getFiftyCentCoinCount() + billsCount);
				capital = capital - (0.50 * billsCount);
								
				// .25 Coins Count
				billsCount = (int) (capital / 0.25);
				monthlyCoinAnalysisList.setTwentyFiveCentCoinCount(monthlyCoinAnalysisList.getTwentyFiveCentCoinCount() + billsCount);
				capital = capital - (0.25 * billsCount);
				
				// .10 Coins Count
				billsCount = (int) (capital / 0.10);
				monthlyCoinAnalysisList.setTenCentCoinCount(monthlyCoinAnalysisList.getTenCentCoinCount() + billsCount);
				capital = capital - (0.10 * billsCount);

				// .05 Coins Count
				billsCount = (int) (capital / 0.05);
				monthlyCoinAnalysisList.setFiveCentCoinsCount(monthlyCoinAnalysisList.getFiveCentCoinsCount() + billsCount);
				capital = capital - (0.05 * billsCount);

				// .02 Coins Count
				billsCount = (int) (capital / 0.02);
				monthlyCoinAnalysisList.setTwoCentCoinsCount(monthlyCoinAnalysisList.getTwoCentCoinsCount() + billsCount);
				capital = capital - (0.02 * billsCount);
				
				// .01 Coins Count
				billsCount = (int) (capital / 0.01);
				monthlyCoinAnalysisList.setOneCentCoinsCount(monthlyCoinAnalysisList.getOneCentCoinsCount() + billsCount);
				capital = capital - (0.01 * billsCount);
			}
		}
		
		return monthlyCoinAnalysisList;
	}
	
	public List<EmployeeSalaryDetails> getEmployeeSalaryDetails(EmployeeSalaryDetailsRequest anEmployeeSalaryDetailsRequest) throws FrontierVisibleException {
		List<EmployeeSalaryDetails> employeeSalaryDetailsList = null;
		List<MonthlyEmployeePayrole> monthlyPayroleList = monthlyEmployeePayroleDao.getEmployeeSalaryDetails(anEmployeeSalaryDetailsRequest);

		if (monthlyPayroleList != null) {
			employeeSalaryDetailsList = new ArrayList<EmployeeSalaryDetails>();
			for (MonthlyEmployeePayrole payrole : monthlyPayroleList) {
				EmployeeSalaryDetails slDetails = new EmployeeSalaryDetails();
				slDetails.setEmployeeId(payrole.getEmployeeId());
				slDetails.setEmployeeName(new EmployeeDaoImplementer().getEmployeeName(payrole.getEmployeeId()));
				slDetails.setBasicSalary(payrole.getBasicSalary());
				slDetails.setEpfEmp(payrole.getEpfEmp());
				slDetails.setEpfComp(payrole.getEpfComp());
				slDetails.setEtfComp(payrole.getEtfComp());
				slDetails.setBankPayment(payrole.getBankPayment());
				slDetails.setPaymentMethod(payrole.getPaymentMethod());
				if ("Cheque".equals(payrole.getPaymentMethod())) {
					slDetails.setBankName(payrole.getBankName());
					slDetails.setBankAccountNo(payrole.getBankAccountNo());					
				}
				employeeSalaryDetailsList.add(slDetails);
			}
		}

		return employeeSalaryDetailsList;
		
	}

	public List<LeaveSummaryDetails> getEmployeeLeaveSummaryDetails(EmployeeLeaveDetailsRequest anEmployeeLeaveDetailsRequest) throws FrontierVisibleException {
		HashMap<String,LeaveSummaryDetails> leaveSummaryDetails = new HashMap<String, LeaveSummaryDetails>();

		List<LeaveRequest>  leaveRequestList = employeeLeaveDao.getEmployeeLeaveSummaryDetails(anEmployeeLeaveDetailsRequest);
		
		for (LeaveRequest leaveReq: leaveRequestList) {
			String key = leaveReq.getFinancialYear() + "" + leaveReq.getEmployeeId();
			if (!leaveSummaryDetails.containsKey(key)) {
				LeaveSummaryDetails leaveSummary = new LeaveSummaryDetails();
				leaveSummary.setFinancialYear(leaveReq.getFinancialYear());
				leaveSummary.setEmployeeId(leaveReq.getEmployeeId());
				leaveSummary.setEmployeeName(new EmployeeDaoImplementer().getEmployeeName(leaveReq.getEmployeeId()));
				leaveSummaryDetails.put(key, leaveSummary);
			}

			LeaveSummaryDetails obj = leaveSummaryDetails.get(key);
			int leaveCount = getLeaveDaysCount(leaveReq);
			if (leaveReq.getLeaveType().equals("Annual")) {
				obj.setAnnualLeaveCount(obj.getAnnualLeaveCount() + leaveCount);				
			} else if (leaveReq.getLeaveType().equals("Casual")) {
				obj.setCasualLeaveCount(obj.getCasualLeaveCount() + leaveCount);
			} else if (leaveReq.getLeaveType().equals("Medical")) {
				obj.setMedicalLeaveCount(obj.getMedicalLeaveCount() + leaveCount);
			} else if (leaveReq.getLeaveType().equals("Lieu")) {
				obj.setLieuLeaveCount(obj.getLieuLeaveCount() + leaveCount);
			} else if (leaveReq.getLeaveType().equals("MatOrPat")) {
				obj.setMatpatLeaveCount(obj.getMatpatLeaveCount() + leaveCount);
			}
			obj.setTotalLeaveUtilizedCount(obj.getTotalLeaveUtilizedCount() + leaveCount);
		}

		return (new ArrayList<LeaveSummaryDetails>(leaveSummaryDetails.values()));
	}


	private int getLeaveDaysCount(LeaveRequest aLeaveRequest) {
		int count = 0;
		try {
			count = dtUtility.getWorkingDaysCountForGivenDateRange(aLeaveRequest.getFromDate(), aLeaveRequest.getToDate()) - 
							new PublicHolidayDaoImplementer().getAvailablePublicHolidayRecordCountForDateRange(aLeaveRequest.getFromDate(), aLeaveRequest.getToDate());
		} catch (FrontierVisibleException e) {
			// This should be empty block
		}
		return count;
	}
}
